﻿using System;
using System.Collections.Generic;
using System.Dynamic;
using System.Xml.Linq;

namespace SB.Xml
{
    /// <summary>
    /// XmlSlurper
    /// </summary>
    public class XmlSlurper
    {
        /// <summary>
        /// Parses an contents of xml file into a dynamic object representation
        /// </summary>
        /// <param name="xmlFilePath">Xml File Path</param>
        /// <returns>dynamic object</returns>
        public dynamic ParseXmlFile(String xmlFilePath)
        {
            dynamic retVal = null;
            XDocument doc = XDocument.Load(xmlFilePath);
            retVal = ReadElement(doc.Root);
            return retVal;
        }
        /// <summary>
        /// Parses an xml string into a dynamic object representation
        /// </summary>
        /// <param name="xmlText">Xml Text</param>
        /// <returns>dynamic object</returns>
        public dynamic ParseXmlText(String xmlText)
        {
            dynamic retVal = null;
            XDocument doc = XDocument.Load(xmlText);
            retVal = ReadElement(doc.Root);
            return retVal;
        }
        /// <summary>
        /// Read Individual Elements Recursively
        /// </summary>
        /// <param name="e">XmlElement</param>
        /// <returns>ExpandoObject</returns>
        private dynamic ReadElement(XElement e)
        {
            dynamic obj = new ExpandoObject();
            IDictionary<string, object> dict = obj as IDictionary<string, object>;
            foreach (var a in e.Attributes())
            {
                dict[a.Name.LocalName] = a.Value;
            }
            List<ExpandoObject> list = new List<ExpandoObject>();
            foreach (var child in e.Elements())
            {
                if (child.HasElements)
                {
                    SetElement(dict, list, child);
                }
                else
                {
                    dict[child.Name.LocalName] = child.Value;
                }
            }


            return obj;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dict"></param>
        /// <param name="list"></param>
        /// <param name="child"></param>
        private void SetElement(IDictionary<string, object> dict, List<ExpandoObject> list, XElement child)
        {
            if (dict.ContainsKey(child.Name.LocalName))
            {
                if (dict[child.Name.LocalName].GetType().Name != "List<ExpandoObject>")
                {
                    list.Add(dict[child.Name.LocalName] as ExpandoObject);
                    list.Add(ReadElement(child));
                    dict[child.Name.LocalName] = list;

                }
                else
                {
                    (dict[child.Name.LocalName] as List<ExpandoObject>).Add(ReadElement(child));
                }
            }
            else
            {
                dict[child.Name.LocalName] = ReadElement(child);
            }
        }
    }
}
